The Memory Manager provides three routines for copying blocks of memory referenced by pointers. To copy a block of memory to a nonrelocatable block, use the BlockMove procedure. To copy to a new relocatable block, use the PtrToHand function. To copy to an existing relocatable block, use the PtrToXHand function. If you want to use any of these routines to copy memory you access with a handle, you must first dereference and lock the handle. A fourth routine, HandToHand , allows you to copy information from one handle to another.
To concatenate blocks of memory, you can use the HandAndHand and PtrAndHand functions.
To copy a sequence of bytes from one location in memory to another, you can use the BlockMove procedure.
PROCEDURE BlockMove (sourcePtr, destPtr: Ptr; byteCount: Size);
The BlockMove procedure moves a block of byteCount consecutive bytes from the address designated by sourcePtr to that designated by destPtr . It updates no pointers.
The BlockMove procedure works correctly even if the source and destination blocks overlap.
You can safely call BlockMove at interrupt time. Even though it moves memory, BlockMove does not move relocatable blocks, but simply copies bytes.
The BlockMove procedure currently flushes the processor caches whenever the number of bytes to be moved is greater than 12. This behavior can adversely affect your application's performance. You might want to avoid calling BlockMove to move small amounts of data in memory if there is no possibility of moving stale data or instructions. For more information about stale data and instructions, see the discussion of the processor caches in the chapter "Memory Management Utilities" in this book.
To copy data referenced by a pointer to a new relocatable block, use the PtrToHand function.
FUNCTION PtrToHand (srcPtr: Ptr; VAR dstHndl: Handle;
size: LongInt): OSErr;
The PtrToHand function returns, in dstHndl , a newly created handle to a copy of the number of bytes specified by the size parameter, beginning at the location specified by srcPtr . The dstHndl parameter must be a handle variable that is not empty and is not a handle to an allocated block of size 0.
Because PtrToHand allocates memory, you should not call it at interrupt time.
You can use the PtrToHand function to copy data from one handle to a new handle if you dereference and lock the source handle. However, if you want to copy all of the data from one handle to another, the HandToHand function (described on HandToHand ) is more efficient.
To copy data referenced by a pointer to an already existing relocatable block, use the PtrToXHand function.
FUNCTION PtrToXHand (srcPtr: Ptr; dstHndl: Handle; size: LongInt):
OSErr;
The PtrToXHand function makes the existing handle, specified by dstHndl , a handle to a copy of the number of bytes specified by the size parameter, beginning at the location specified by srcPtr .
Use the HandToHand function to copy all of the data from one relocatable block to a new relocatable block.
FUNCTION HandToHand (VAR theHndl: Handle): OSErr;
The HandToHand function attempts to copy the information in the relocatable block to which theHndl is a handle; if successful, HandToHand returns a handle to the new relocatable block in theHndl . The new relocatable block is created in the same heap zone as the original block (which might not be the current heap zone).
Because HandToHand replaces its input parameter with the new handle, you should retain the original value of the input parameter somewhere else, or you won't be able to access it. Here is an example:
VAR
original, copy: Handle;
myErr: OSErr;
...
copy := original; {both handles access same block}
myErr := HandToHand(copy); {copy now points to copy of block}
If successful in creating a new relocatable block, the HandToHand function does not duplicate the properties of the original block. The new block is unlocked, unpurgeable, and not a resource. You might need to call HLock , HPurge , or HSetRBit (or the combination of HGetState and HSetState ) to adjust the properties of the new block.
Because HandToHand allocates memory, you should not call it at interrupt time.
If you want to copy only part of a relocatable block into a new relocatable block, use the PtrToHand function, described on PtrToHand , after locking and dereferencing a handle to the relocatable block to be copied.
Use the HandAndHand function to concatenate two relocatable blocks.
FUNCTION HandAndHand (aHndl, bHndl: Handle): OSErr;
The HandAndHand function concatenates the information from the relocatable block to which aHndl is a handle onto the end of the relocatable block to which bHndl is a handle. The aHndl variable remains unchanged.
The HandAndHand function dereferences the handle aHndl . You must call the HLock procedure to lock the block before calling HandAndHand . Afterward, you can call the HUnlock procedure to unlock it. Alternatively, you can save the block's original state by calling the HGetState function, lock the block by calling HLock , and then restore the original settings by calling HSetState .
Use the PtrAndHand function to concatenate part or all of a memory block to the end of a relocatable block.
FUNCTION PtrAndHand (pntr: Ptr; hndl: Handle; size: LongInt):
OSErr;
The PtrAndHand function takes the number of bytes specified by the size parameter, beginning at the location specified by pntr , and concatenates them onto the end of the relocatable block to which hndl is a handle.
Because PtrAndHand allocates memory, you should not call it at interrupt time.